package com.mall.user.services;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.IUserService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.converter.UserConverterMapper;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.entitys.UserVerify;
import com.mall.user.dal.persistence.MemberMapper;

import com.mall.user.dal.persistence.UserVerifyMapper;
import com.mall.user.dto.UserLoginRequest;
import com.mall.user.dto.UserLoginResponse;
import com.mall.user.dto.UserRegisterRequest;
import com.mall.user.dto.UserRegisterResponse;
import com.mall.user.utils.EmailUtil;

import com.mall.user.dto.*;

import com.mall.user.utils.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

/**
 * @author: thz
 * @class: UserServiceImpl
 */

@Slf4j
@Component
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements IUserService {

    @Autowired
    MemberMapper memberMapper;

    @Autowired
    UserConverterMapper userConverterMapper;

    @Autowired
    RedissonClient redissonClient;
    @Autowired
    EmailUtil emailUtil;
    @Autowired
    UserVerifyMapper userVerifyMapper;

    @Override
    public UserRegisterResponse userRegister(UserRegisterRequest request, String uuid) {
        UserRegisterResponse response = new UserRegisterResponse();
        try {
            request.requestCheck();

            String redisKey = "kaptcha_uuid" + uuid;
            RBucket<String> rBucket = redissonClient.getBucket(redisKey);
            String code = rBucket.get();
            if (!code.equals(request.getCaptcha())) {
                response.setCode(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getCode());
                response.setMsg(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getMessage());
                return response;
            }

            Member member = userConverterMapper.converter(request);
            member.setCreated(new Date());
            member.setUpdated(new Date());
            memberMapper.insertSelective(member);
            response.setCode(SysRetCodeConstants.SUCCESS.getCode());
            response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());

            UserVerify userVerify = new UserVerify();
            userVerify.setUsername(member.getUsername());
            userVerify.setRegisterDate(new Date());
            userVerify.setUuid(uuid);
            userVerify.setCisVerify("N");
            userVerify.setCisExpire("N");
            userVerifyMapper.insertSelective(userVerify);


        } catch (DuplicateKeyException e) {
            response.setCode(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getCode());
            response.setMsg(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getMessage());
        } catch (ValidateException e) {
            response.setCode(e.getErrorCode());
            response.setMsg(e.getMessage());
        }

        return response;
    }

    @Override
    public UserLoginResponse userLogin(UserLoginRequest request, String uuid) {
        UserLoginResponse response = new UserLoginResponse();
        try {
            request.requestCheck();

            String redisKey = "kaptcha_uuid" + uuid;
            RBucket<String> rBucket = redissonClient.getBucket(redisKey);
            String code = rBucket.get();
            if (!code.equals(request.getCaptcha())) {
                response.setCode(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getCode());
                response.setMsg(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getMessage());
                return response;
            }

            Example example = new Example(Member.class);
            example.createCriteria().andEqualTo("username", request.getUserName()).
                    andEqualTo("password", request.getPassword());
            List<Member> members = memberMapper.selectByExample(example);
            if ("N".equals(members.get(0).getIsVerified())) {
                response.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR.getCode());
                response.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR.getMessage());
                return response;
            }

            response = userConverterMapper.converter(members.get(0));
            UsernameIdToken usernameIdToken = new UsernameIdToken(response.getUsername(), response.getId());
            ObjectMapper objectMapper = new ObjectMapper();
            String tokenJson = objectMapper.writeValueAsString(usernameIdToken);

            String token = JwtTokenUtils.builder().msg(tokenJson).build().creatJwtToken();
            response.setToken(token);
            response.setCode(SysRetCodeConstants.SUCCESS.getCode());
            response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        } catch (Exception e) {
            response.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            response.setMsg(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
        }
        return response;
    }

    @Override

    public void sendEmail(String email, String uuid, String userName) {
        emailUtil.changeCode2(email, uuid, userName);
    }

    @Override
    public QueryMemberResponse getUserDataResponse(QueryMemberRequest request) {
        QueryMemberResponse response = new QueryMemberResponse();
        try {
            request.requestCheck();

            Long userId = request.getUserId();
            Member member = memberMapper.selectByPrimaryKey(userId);
            response = userConverterMapper.converter2(member);
            response.setCode(SysRetCodeConstants.SUCCESS.getCode());
            response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());

        } catch (Exception e) {
            response.setCode(SysRetCodeConstants.DATA_NOT_EXIST.getCode());
            response.setMsg(SysRetCodeConstants.DATA_NOT_EXIST.getMessage());
        }
        return response;

    }
}
